package com.loe.ktui

import android.app.Activity
import android.content.Context
import android.content.res.Resources
import android.os.Handler
import android.os.Looper
import android.text.Editable
import android.text.Html
import android.text.Spanned
import android.text.TextWatcher
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.text.HtmlCompat
import androidx.fragment.app.Fragment
import com.loe.ktui.util.KtCornerProvider

const val WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT
const val MATCH_PARENT = ViewGroup.LayoutParams.MATCH_PARENT

const val HORIZONTAL = LinearLayout.HORIZONTAL
const val VERTICAL = LinearLayout.VERTICAL

inline val Context.screenWidthDp: Int get() = resources.configuration.screenWidthDp
inline val Context.screenHeightDp: Int get() = resources.configuration.screenHeightDp

inline val statusHeight: Int
    get()
    {
        val resourceId = Resources.getSystem().getIdentifier("status_bar_height", "dimen", "android")
        return Resources.getSystem().getDimensionPixelSize(resourceId)
    }

inline val Any?.dist: Int
    get()
    {
        if (this is String)
        {
            return toInt()
        }
        if (this == WRAP_CONTENT || this == MATCH_PARENT)
        {
            return this as Int
        }
        if (this != null)
        {
            return (toString().toDouble() * Resources.getSystem().displayMetrics.density + 0.5).toInt()
        }
        return 0
    }

inline val Any?.distFloat: Float
    get()
    {
        if (this is String)
        {
            return toFloat()
        }
        if (this != null)
        {
            return toString().toFloat() * Resources.getSystem().displayMetrics.density
        }
        return 0f
    }

fun <T : View> View.findView(id: String): T = findViewById(KtUi.getId(id))
fun <T : View> Activity.findView(id: String): T = findViewById(KtUi.getId(id))
fun <T : View> Fragment.findView(id: String): T = view!!.findViewById(KtUi.getId(id))

fun Activity.setContentUI(id: String? = null, block: (UiFrameLayout.() -> Unit)? = null)
{
    val ui = UiFrameLayout(id)
    block?.let { ui.it() }
    setContentView(ui.createView(this))
}

inline var Activity.contentUI: UiView?
    get() = null
    set(value)
    {
        setContentView(value?.createView(this))
    }

/******************************************* 工具 ******************************************/

internal inline fun ktSafe(run: () -> Unit)
{
    try
    {
        run()
    } catch (e: Exception)
    {
        Log.e("KtUiRuntime", "" + e)
    }
}

internal fun TextView?.addKtTextAfterListener(after: (s: String) -> Unit)
{
    this?.addTextChangedListener(object : TextWatcher
    {
        override fun afterTextChanged(s: Editable?)
        {
            after(s.toString())
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int)
        {
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int)
        {
        }
    })
}

internal fun View?.setKtDelayClickListener(delay: Long = 0, interval: Long = 1200, onClick: (v: View) -> Unit)
{
    var t = 0L
    this?.setOnClickListener()
    {
        if (System.currentTimeMillis() - t > interval)
        {
            postDelayed({ onClick(it) }, delay)
            t = System.currentTimeMillis()
        }
    }
}

val ktHandler by lazy { Handler(Looper.getMainLooper()) }

internal fun ktDelay(delay: Long? = null, run: () -> Unit): DelayTask
{
    return object : DelayTask(delay)
    {
        override fun run()
        {
            run()
        }
    }.start()
}

internal abstract class DelayTask(private val delay: Long? = null) : Runnable
{
    fun start(): DelayTask
    {
        if (delay == null)
        {
            ktHandler.post(this)
        } else
        {
            ktHandler.postDelayed(this, delay)
        }

        return this
    }

    fun stop()
    {
        ktHandler.removeCallbacks(this)
    }
}

val KtDirects = listOf("left", "top", "right", "bottom", "")

internal inline val String.ktHtml: Spanned
    get() = HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_LEGACY)

internal fun String.ktC(c: String): String
{
    if (c.isEmpty()) return this
    return "<font color='$c'>$this</font>"
}

fun ktPx(dp: Double): Int
{
    return (dp * Resources.getSystem().displayMetrics.density + 0.5).toInt()
}

fun ktPx(dp: Int): Int
{
    return (dp * Resources.getSystem().displayMetrics.density + 0.5).toInt()
}

fun ktDp(px: Double): Float
{
    return (px / Resources.getSystem().displayMetrics.density + 0.5).toFloat()
}

var View.marginTop: Int?
    get() = ktDp((layoutParams as? ViewGroup.MarginLayoutParams)?.topMargin?.toDouble() ?: 0.0).toInt()
    set(value)
    {
        if (value != null)
        {
            val params = layoutParams as? ViewGroup.MarginLayoutParams
            params?.topMargin = ktPx(value.toDouble())
            layoutParams = params
        }
    }

var View.marginTopPx: Int
    get() = (layoutParams as? ViewGroup.MarginLayoutParams)?.topMargin ?: 0
    set(value)
    {
        val params = layoutParams as? ViewGroup.MarginLayoutParams
        params?.topMargin = value
        layoutParams = params
    }

var View.marginBottom: Int?
    get() = ktDp((layoutParams as? ViewGroup.MarginLayoutParams)?.bottomMargin?.toDouble() ?: 0.0).toInt()
    set(value)
    {
        if (value != null)
        {
            val params = layoutParams as? ViewGroup.MarginLayoutParams
            params?.bottomMargin = ktPx(value.toDouble())
            layoutParams = params
        }
    }

var View.marginBottomPx: Int
    get() = (layoutParams as? ViewGroup.MarginLayoutParams)?.bottomMargin ?: 0
    set(value)
    {
        val params = layoutParams as? ViewGroup.MarginLayoutParams
        params?.bottomMargin = value
        layoutParams = params
    }

var View.marginLeft: Int?
    get() = ktDp((layoutParams as? ViewGroup.MarginLayoutParams)?.leftMargin?.toDouble() ?: 0.0).toInt()
    set(value)
    {
        if (value != null)
        {
            val params = layoutParams as? ViewGroup.MarginLayoutParams
            params?.leftMargin = ktPx(value.toDouble())
            layoutParams = params
        }
    }

var View.marginLeftPx: Int
    get() = (layoutParams as? ViewGroup.MarginLayoutParams)?.leftMargin ?: 0
    set(value)
    {
        val params = layoutParams as? ViewGroup.MarginLayoutParams
        params?.leftMargin = value
        layoutParams = params
    }

var View.marginRight: Int?
    get() = ktDp((layoutParams as? ViewGroup.MarginLayoutParams)?.rightMargin?.toDouble() ?: 0.0).toInt()
    set(value)
    {
        if (value != null)
        {
            val params = layoutParams as? ViewGroup.MarginLayoutParams
            params?.rightMargin = ktPx(value.toDouble())
            layoutParams = params
        }
    }

var View.marginRightPx: Int
    get() = (layoutParams as? ViewGroup.MarginLayoutParams)?.rightMargin ?: 0
    set(value)
    {
        val params = layoutParams as? ViewGroup.MarginLayoutParams
        params?.rightMargin = value
        layoutParams = params
    }

var View.marginHorizontal: Int?
    get() = ktDp((layoutParams as? ViewGroup.MarginLayoutParams)?.rightMargin?.toDouble() ?: 0.0).toInt()
    set(value)
    {
        if (value != null)
        {
            val params = layoutParams as? ViewGroup.MarginLayoutParams
            val v = ktPx(value.toDouble())
            params?.leftMargin = v
            params?.rightMargin = v
            layoutParams = params
        }
    }

var View.marginVertical: Int?
    get() = ktDp((layoutParams as? ViewGroup.MarginLayoutParams)?.topMargin?.toDouble() ?: 0.0).toInt()
    set(value)
    {
        if (value != null)
        {
            val params = layoutParams as? ViewGroup.MarginLayoutParams
            val v = ktPx(value.toDouble())
            params?.topMargin = v
            params?.bottomMargin = v
            layoutParams = params
        }
    }

var View.margin: Int?
    get() = ktDp((layoutParams as? ViewGroup.MarginLayoutParams)?.topMargin?.toDouble() ?: 0.0).toInt()
    set(value)
    {
        if (value != null)
        {
            val params = layoutParams as? ViewGroup.MarginLayoutParams
            val v = ktPx(value.toDouble())
            params?.leftMargin = v
            params?.rightMargin = v
            params?.topMargin = v
            params?.bottomMargin = v
            layoutParams = params
        }
    }

fun View?.setCorner(corner: Any, cornerDirect: String? = null)
{
    this?.outlineProvider = KtCornerProvider(corner.dist, cornerDirect ?: "", this!!)
}
